<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ci="http://apache.org/cocoon/include/1.0" xmlns:cu="http://apache.org/cocoon/counit"
  xmlns:source="http://apache.org/cocoon/source/1.0" xmlns:xslt="xslt" version="1.0">

  <xsl:namespace-alias stylesheet-prefix="xslt" result-prefix="xsl"/>

  <xsl:param name="timestamp"/>

  <xsl:template match="cu:testcase[cu:output-filter]">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:variable name="filter-file">
        <xsl:text>temp_filter_</xsl:text>
        <xsl:value-of select="generate-id()"/>
        <xsl:text>_</xsl:text>
        <xsl:value-of select="$timestamp"/>
        <xsl:text>.xsl</xsl:text>
      </xsl:variable>
      <xsl:apply-templates mode="output-filter">
        <xsl:with-param name="filter-file" select="$filter-file"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <!-- add sourcewriting stuff-->
  <xsl:template match="cu:output-filter" mode="output-filter">
    <xsl:param name="filter-file"/>
    <xsl:if test="not(@src)">
      <source:write>
        <source:source>
          <xsl:value-of select="$filter-file"/>
        </source:source>
        <source:fragment>
          <xslt:stylesheet version="1.0">

            <!-- copy 'namespace attributes', which cause the
            namespaces to be copied to the generated stylesheet. 
            There seems to be no other way :( -->
            <xsl:for-each select="@*[local-name()='include-namespace']">
              <xsl:copy-of select="."/>
            </xsl:for-each>

            <xsl:variable name="action">
              <xsl:choose>
                <xsl:when test="@action">
                  <xsl:value-of select="@action"/>
                </xsl:when>
                <!-- the default value -->
                <xsl:otherwise>
                  <xsl:text>remove-all</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:variable>

            <xsl:if test="not($action='preserve-all' or $action='remove-all')">
              <xsl:message terminate="yes">
                <xsl:value-of select="parent::cu:*/@id"/>
                <xsl:text>, output-filter action  is not supported for value:</xsl:text>
                <xsl:value-of select="$action"/>
              </xsl:message>
            </xsl:if>
            
            <!-- start output in @action mode -->
            <xslt:template match="/">
              <xsl:choose>
                <xsl:when test="string-length(@use-root-element) &gt; 0">
                  <!-- provide a single root element -->
                  <xsl:element name="{@use-root-element}">
                    <xslt:apply-templates mode="{$action}"/>
                  </xsl:element>
                </xsl:when>
                <xsl:otherwise>
                  <!-- no root element needed -->
                  <xslt:apply-templates mode="{$action}"/>
                </xsl:otherwise>
              </xsl:choose>
            </xslt:template>

            <xslt:template match="node()|@*" mode="preserve-all">
              <xslt:copy>
                <xslt:apply-templates select="@*|node()" mode="preserve-all"/>
              </xslt:copy>
            </xslt:template>

            <xslt:template match="node()|@*" mode="remove-all">
              <xslt:apply-templates select="node()|@*" mode="remove-all"/>
            </xslt:template>
            <xslt:template match="text()" mode="remove-all"/>

            <!-- inclusions and exclusions -->
            <xsl:apply-templates mode="output-filter"/>

          </xslt:stylesheet>
        </source:fragment>
      </source:write>
    </xsl:if>
  </xsl:template>

  <!-- keep some elements -->
  <xsl:template match="cu:preserve" mode="output-filter">
    <!-- switch to preserve-mode while in the remove-all mode -->
    <xslt:template match="{@select}" mode="remove-all" priority="{count(../*) - position() + 1}">
      <xslt:copy>
        <xslt:apply-templates select="@*|node()" mode="preserve-all"/>
      </xslt:copy>
    </xslt:template>
  </xsl:template>
  <!-- remove some elements -->
  <xsl:template match="cu:remove" mode="output-filter" >
    <!-- switch to remove mode while in the preserve mode-->
    <xslt:template match="{@select}" mode="preserve-all" priority="{count(../*) - position() + 1}">
      <xslt:apply-templates select="@*|node()" mode="remove-all"/>
    </xslt:template>
  </xsl:template>

  <!-- add a request parameter to the cinclude -->
  <xsl:template match="ci:parameters" mode="output-filter">
    <xsl:param name="filter-file"/>
    <xsl:variable name="base" select="ancestor::cu:testsuite[1]/@base"/>
    <xsl:variable name="testsuite-dir" select="ancestor::cu:testsuite[1]/@testsuite-dir"/>
    <xsl:variable name="src" select="ancestor::cu:testcase/cu:output-filter/@src"/>

    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
      <ci:parameter>
        <ci:name>counit-output-filter</ci:name>
        <ci:value>true</ci:value>
      </ci:parameter>
      <ci:parameter>
        <ci:name>counit-output-filter-src</ci:name>
        <ci:value>
          <!-- file or generated xsl? -->
          <xsl:variable name="filter">
            <xsl:choose>
              <xsl:when test="$src">
                <xsl:value-of select="concat($base, $testsuite-dir, $src)"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$filter-file"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:variable>
          <xsl:value-of select="$filter"/>
        </ci:value>
      </ci:parameter>
    </xsl:copy>
  </xsl:template>

  <!-- copy everything else in filter mode-->
  <xsl:template match="node()|@*" mode="output-filter">
    <xsl:param name="filter-file"/>
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()" mode="output-filter">
        <xsl:with-param name="filter-file" select="$filter-file"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <!-- copy everything else in normal mode-->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
